﻿using ImageMagick;
using iTextSharp.text;
using iTextSharp.text.pdf;

using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Reflection.Metadata;
using System.Runtime.Intrinsics.Arm;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Tesseract;
using Image = SixLabors.ImageSharp.Image;

namespace ConsoleApp1
{
    internal class Helper
    {
        public static void AddOcrTextToPdfWorkflow(string inputPdf)
        {
            // 临时目录准备
            var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
            Directory.CreateDirectory(tempDir);

            try
            {
                // 步骤1：PDF转图片（带页码）
                var imagePaths = ConvertPdfToImages(inputPdf, @"D:\output");

                // 步骤2：OCR识别带坐标的文本
                var allResults = new List<OcrResult>();
                for (int i = 0; i < imagePaths.Count; i++)
                {
                    var results = GetTextWithCoordinates(imagePaths[i]);
                    results.ForEach(r => r.PageNum = i + 1); // 记录页码
                    allResults.AddRange(results);
                }

                // 步骤3：将图片合并为PDF
                var imagePdfPath = Path.Combine(Path.GetDirectoryName(inputPdf),
                    Path.GetFileNameWithoutExtension(inputPdf) + "_with_image.pdf");
                MergeImagesToPdf(imagePaths, imagePdfPath);

                // 步骤4：将OCR文本添加到PDF
                var outputPath = Path.Combine(Path.GetDirectoryName(inputPdf),
                    Path.GetFileNameWithoutExtension(inputPdf) + "_with_ocr.pdf");
                AddOcrTextToPdf(imagePdfPath, outputPath, allResults);

                //书签
                var bookmarks = DetectBookmarks(allResults);
                var outputbookmarkPath = Path.Combine(Path.GetDirectoryName(inputPdf),
                    Path.GetFileNameWithoutExtension(inputPdf) + "_with_bookmark.pdf");
                AddBookMarkToPdf(imagePdfPath, outputPath, bookmarks);

                Console.WriteLine($"生成成功：{outputPath}");
            }
            finally
            {
                Directory.Delete(tempDir, true); // 清理临时文件
            }
        }

        public static List<string> ConvertPdfToImages(string pdfPath, string outputFolder)
        {
            MagickNET.SetGhostscriptDirectory(@"D:\Work\other\A\PdfRender20250214\gostscript");
            var outputs = new List<string>();
            var settings = new MagickReadSettings
            {
                Density = new Density(300, 300),
                //BackgroundColor = MagickColors.White
            };
            // 创建一个MagickImageCollection对象
            using (MagickImageCollection collection = new MagickImageCollection())
            {
                // 加载PDF文件
                collection.Read(pdfPath, settings);
                // 遍历PDF中的每一页
                for (int i = 0; i < collection.Count; i++)
                {
                    //collection.Flatten();
                    // 为每一页生成一个唯一的文件名
                    string outputPath = System.IO.Path.Combine(outputFolder, $"page_{i + 1}.png");

                    var image = collection[i] as MagickImage;
                    // 保存为PNG图片
                    image.Write(outputPath);

                    //ProcessImageWithTransparency(outputPath, outputPath + "_processed.png");

                    outputs.Add(outputPath);
                }
            }

            return outputs;
        }

        public static void ProcessImageWithTransparency(string inputPath, string outputPath)
        {
            // 加载PNG图片（自动识别透明度通道）
            using (Image<Rgba32> image = Image.Load<Rgba32>(inputPath))
            {
                for (int row = 0; row < image.Height; row++)
                {
                    for (int col = 0; col < image.Width; col++)
                    {
                        var pixel = image[col, row];
                        pixel.A = 1;
                    }
                }

                // 保存处理后的图片（保持PNG透明度）
                image.Save(outputPath, new PngEncoder
                {
                    CompressionLevel = PngCompressionLevel.BestCompression,
                    ColorType = PngColorType.RgbWithAlpha // 强制保留Alpha通道
                });
            }
        }

        public static void MergeImagesToPdf(List<string> imagePaths, string outputPdfPath)
        {
            using var images = new MagickImageCollection();

            foreach (var image in imagePaths)
            {
                images.Add(new MagickImage(image));
            }

            images.Write(outputPdfPath);
        }

        public static List<OcrResult> GetTextWithCoordinates(string imagePath, string lang = "chi_sim+eng")
        {
            var results = new List<OcrResult>();

            using (var engine = new TesseractEngine("D:\\Work\\other\\A\\PdfRender20250214\\tessdata", lang, EngineMode.TesseractAndLstm))
            {
                engine.SetVariable("preserve_interword_spaces", 0);//减少空格问题
                //engine.SetVariable("textord_heavy_nr", 0);
                //engine.SetVariable("textord_old_xheight", 0);
                //engine.SetVariable("textord_min_linesize", 1.5);
                //engine.SetVariable("edges_use_new_outline_complexity", 1);
                //engine.SetVariable("textord_space_size_is_variable", 1);
                using (var img = Pix.LoadFromFile(imagePath))
                using (var page = engine.Process(img, PageSegMode.SingleBlock))
                {
                    var elements = page.GetIterator();
                    do
                    {
                        if (elements.TryGetBoundingBox(PageIteratorLevel.TextLine, out var rect))
                        {
                            var text = elements.GetText(PageIteratorLevel.TextLine);
                            text = Regex.Replace(text, @"\s", "");
                            results.Add(new OcrResult
                            {
                                Text = text,
                                X = rect.X1,
                                Y = img.Height - rect.Y2, // 转换为PDF坐标系
                                Width = rect.Width,
                                Height = rect.Height,
                                ImgHeight = img.Height,
                                ImgWidth = img.Width,
                                Confidence = elements.GetConfidence(PageIteratorLevel.TextLine)
                            });
                        }
                    } while (elements.Next(PageIteratorLevel.TextLine));
                }
            }

            return results;
        }

        private static float GetFontSize(string text, BaseFont font, float maxWidth, float initialFontSize)
        {
            float fontSize = initialFontSize;
            float textWidth = font.GetWidthPoint(text, fontSize);

            while (textWidth > maxWidth)
            {
                fontSize -= 0.1f;
                textWidth = font.GetWidthPoint(text, fontSize);
            }

            return fontSize;
        }

        public static void AddOcrTextToPdf(string inputPdf, string outputPdf, List<OcrResult> ocrResults)
        {
            using (var reader = new PdfReader(inputPdf))
            using (var fs = new FileStream(outputPdf, FileMode.Create))
            {
                var stamper = new PdfStamper(reader, fs);

                for (int i = 1; i <= reader.NumberOfPages; i++)
                {
                    var pageSize = reader.GetPageSize(i);
                    var cb = stamper.GetUnderContent(i); // 获取页面内容

                    // 1. 配置中文字体
                    string fontPath = "C:/Windows/Fonts/simhei.ttf";
                    BaseFont baseFont = BaseFont.CreateFont(fontPath, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);

                    // 3. 添加文本
                    //cb.BeginText();
                    //cb.SetFontAndSize(baseFont, 12);
                    //cb.SetColorFill(BaseColor.Black);
                    //cb.ShowTextAligned(PdfContentByte.ALIGN_LEFT, "可搜索的文本", 100, 500, 0);
                    //cb.EndText();

                    // 设置文本透明度为0（不可见）
                    PdfGState gState = new PdfGState();
                    gState.FillOpacity = 0;
                    cb.SetGState(gState);

                    // 过滤当前页的OCR结果
                    var pageResults = ocrResults
                        .Where(r => r.PageNum == i)
                        .ToList();

                    float adjustmentFactor = 1.2f; // 经验调整系数

                    foreach (var result in pageResults)
                    {
                        // 设置字体和颜色
                        //string fontPath = "C:/Windows/Fonts/simhei.ttf";
                        //BaseFont baseFont = BaseFont.CreateFont(fontPath, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
                        //var color = new BaseColor(0, 0, 0); // 黑色

                        // 计算字体大小
                        float fontSizeInPoints = (Math.Min(result.Height, result.Width) * 72 / 300) * adjustmentFactor;

                        var fontSize = GetFontSize(result.Text, baseFont, result.Width, fontSizeInPoints);

                        var pdfX = result.X / result.ImgWidth * pageSize.Width;
                        var pdfY = result.Y / result.ImgHeight * pageSize.Height;
                        // 添加文本
                        cb.BeginText();
                        cb.SetFontAndSize(baseFont, fontSize); // 字体大小与OCR结果高度一致
                        cb.SetColorFill(BaseColor.Black);
                        cb.ShowTextAligned(PdfContentByte.ALIGN_LEFT, result.Text, pdfX, pdfY, 0);
                        cb.EndText();
                    }
                }

                stamper.Close();
            }
        }

        public static void AddBookMarkToPdf(string inputPdf, string outputPdf, List<BookmarkItem> bookmarks)
        {
        }

        private static List<BookmarkItem> DetectBookmarks(List<OcrResult> ocrResults)
        {
            var bookmarks = new List<BookmarkItem>();

            foreach (var result in ocrResults.Where(r => r.Confidence > 80))
            {
                var text = result.Text.Trim();

                // 使用正则匹配标题模式
                if (Regex.IsMatch(text, @"^(第[一二三四五六七八九十]+章|Chapter\s\d+)"))
                {
                    bookmarks.Add(new BookmarkItem
                    {
                        Title = text,
                        PageNumber = result.PageNum,
                        YPosition = result.Y,
                        Level = 1
                    });
                }
                else if (Regex.IsMatch(text, @"^(\d+\.\d+|\d+\.)")) // 匹配子标题
                {
                    bookmarks.Add(new BookmarkItem
                    {
                        Title = text,
                        PageNumber = result.PageNum,
                        YPosition = result.Y,
                        Level = 2
                    });
                }
            }

            return bookmarks;
        }

        //public static void MergeImagesToPdf(List<string> imagePaths, string outputPdfPath)
        //{
        //    Document doc = new Document(PageSize.A4, 0, 0, 0, 0);
        //    PdfWriter.GetInstance(doc, new FileStream(outputPdfPath, FileMode.Create));
        //    doc.Open();

        // foreach (var path in imagePaths) { Image img = Image.GetInstance(path);
        // img.ScaleToFit(doc.PageSize.Width, doc.PageSize.Height); doc.Add(img); doc.NewPage(); }

        //    doc.Close();
        //}
    }

    public class BookmarkItem
    {
        public string Title { get; set; }
        public int PageNumber { get; set; }
        public float YPosition { get; set; }
        public int Level { get; set; }
    }

    public class OcrResult
    {
        public string Text { get; set; }
        public float X { get; set; }
        public float Y { get; set; }
        public float Width { get; set; }
        public float Height { get; set; }
        public float ImgWidth { get; set; }
        public float ImgHeight { get; set; }
        public float Confidence { get; set; }
        public int PageNum { get; set; }
    }
}